﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;

namespace ZWFrameWork
{
    public class ByteBuffer
    {
        MemoryStream stream = null;
        BinaryWriter writer = null;
        BinaryReader reader = null;
        int m_nLength = 0;
        int m_nCurReadLength = 0;

        public void CopyValue(ByteBuffer origin, ByteBuffer target)
        {
            System.Reflection.PropertyInfo[] properties = (target.GetType()).GetProperties();
            System.Reflection.FieldInfo[] fields = (origin.GetType()).GetFields();
            for (int i = 0; i < fields.Length; i++)
            {
                for (int j = 0; j < properties.Length; j++)
                {
                    Debug.Log("CopyValue properties name " + properties[j].Name + " fields name " + fields[i].Name);
                    if (fields[i].Name == properties[j].Name && properties[j].CanWrite)
                    {
                        properties[j].SetValue(target, fields[i].GetValue(origin), null);
                    }
                }
            }
        }

        public ByteBuffer()
        {
            stream = new MemoryStream();
            writer = new BinaryWriter(stream);
        }

        public ByteBuffer(byte[] data)
        {
            if (data != null)
            {
                stream = new MemoryStream(data);
                reader = new BinaryReader(stream);
                setLength(data.Length);
            }
            else
            {
                stream = new MemoryStream();
                writer = new BinaryWriter(stream);
            }
        }

        //用于客户端创建一个Buffer 赋值后，再解析数据
        public ByteBuffer SetNewReader()
        {
            ByteBuffer buffer = new ByteBuffer(ToBytes());
            Close();
            return buffer;
        }

        public void setLength(int length)
        {
            m_nLength = length;
        }

        public int getLength()
        {
            return m_nLength;
        }

        public int getlen()
        {
            return getLength();
        }

        public void setCurReadLength(int length)
        {
            m_nCurReadLength = length;
        }

        public int getCurReadLength()
        {
            return m_nCurReadLength;
        }

        public int getcurlen()
        {
            return getCurReadLength();
        }

        public void Close()
        {
            if (writer != null) writer.Close();
            if (reader != null) reader.Close();

            stream.Close();
            writer = null;
            reader = null;
            stream = null;
        }

        /// <pushbyte>
        public void WriteByte(byte v)
        {
            writer.Write(v);
            setLength(getLength() + sizeof(byte));
        }

        public void pushbyte(byte v)
        {
            WriteByte(v);
        }

        ///
        /// <pushbool>
        public void WriteBool(bool v)
        {
            writer.Write(v);
            setLength(getLength() + sizeof(bool));
        }

        public void pushbool(bool v)
        {
            WriteBool(v);
        }

        ///
        /// <pushword>
        public void WriteUInt16(UInt16 v)
        {
            writer.Write((UInt16)v);
            setLength(getLength() + sizeof(UInt16));
        }

        public void pushword(UInt16 v)
        {
            WriteUInt16(v);
        }

        ///
        /// <pushdword>
        public void WriteUInt32(UInt32 v)
        {
            writer.Write((UInt32)v);
            setLength(getLength() + sizeof(UInt32));
        }

        public void pushdword(UInt32 v)
        {
            WriteUInt32(v);
        }

        ///
        /// <pushscore>
        public void WriteInt64(Int64 v)
        {
            writer.Write((Int64)v);
            setLength(getLength() + sizeof(Int64));
        }

        public void pushscore(Int64 v)
        {
            WriteInt64(v);
        }

        ///
        /// <pushdouble>
        public void WriteDouble(double v)
        {
            writer.Write(v);
            setLength(getLength() + sizeof(double));
        }

        public void pushdouble(double v)
        {
            WriteDouble(v);
        }

        /// 
        public void WriteInt16(Int16 v)
        {
            writer.Write((Int16)v);
            setLength(getLength() + sizeof(Int16));
        }

        public void WriteInt32(Int32 v)
        {
            writer.Write((Int32)v);
            setLength(getLength() + sizeof(Int32));
        }

        public void WriteSingle(Single v)
        {
            writer.Write((Single)v);
            setLength(getLength() + sizeof(Single));
        }

        /// <pushint>
        public void WriteInt(int v)
        {
            writer.Write((int)v);
            setLength(getLength() + sizeof(int));
        }

        public void pushint(int v)
        {
            WriteInt(v);
        }

        ///
        /// <pushshort>
        public void WriteShort(ushort v)
        {
            writer.Write((ushort)v);
            setLength(getLength() + sizeof(ushort));
        }

        public void pushshort(ushort v)
        {
            WriteShort(v);
        }

        /// 
        public void WriteLong(long v)
        {
            writer.Write((long)v);
            setLength(getLength() + sizeof(long));
        }

        /// <pushfloat>
        public void WriteFloat(float v)
        {
            writer.Write(v);
            setLength(getLength() + sizeof(float));
        }

        public void pushfloat(float v)
        {
            WriteFloat(v);
        }

        ///
        /// <pushstring>
        public void WriteString(string v)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(v);
            writer.Write((ushort)bytes.Length);
            writer.Write(bytes);
            setLength(getLength() + bytes.Length);
        }

        public void pushstring(string v)
        {
            WriteString(v);
        }

        public void WriteString(string v, int length)
        {
            length *= 2;
            byte[] bytes = NetUtils.UTF8ToUTF16(v, length);
            writer.Write(bytes);
            setLength(getLength() + length);
        }

        public void pushstring(string v, int length)
        {
            WriteString(v, length);
        }

        ///
        public void WriteBytes(byte[] v)
        {
            writer.Write(v);
            setLength(getLength() + v.Length);
        }

        //   public void WriteBuffer(LuaByteBuffer strBuffer)
        //   {
        //       WriteBytes(strBuffer.buffer);
        // setLength (getLength () + strBuffer.buffer.Length);
        //   }

        /// <pushstring>
        public bool ReadBool()
        {
            setCurReadLength(getCurReadLength() + sizeof(bool));
            return reader.ReadBoolean();
        }

        public bool readbool()
        {
            return ReadBool();
        }

        ///
        /// <readbyte>
        public byte ReadByte()
        {
            setCurReadLength(getCurReadLength() + sizeof(byte));
            return reader.ReadByte();
        }

        public byte readbyte()
        {
            return ReadByte();
        }

        ///
        /// <reaword>
        public UInt16 ReadUInt16()
        {
            setCurReadLength(getCurReadLength() + sizeof(UInt16));
            return (UInt16)reader.ReadUInt16();
        }

        public UInt16 readword()
        {
            return ReadUInt16();
        }

        
        public UInt64 ReadUInt64()
        {
            setCurReadLength(getCurReadLength() + sizeof(UInt64));
            return (UInt64)reader.ReadUInt64();
        }


        ///
        /// <readword>
        public UInt32 ReadUInt32()
        {
            setCurReadLength(getCurReadLength() + sizeof(UInt32));
            return (UInt32)reader.ReadUInt32();
        }

        public UInt32 readdword()
        {
            return ReadUInt32();
        }

        ///
        /// <readscore>
        public string ReadInt64()
        {
            setCurReadLength(getCurReadLength() + sizeof(Int64));
            return reader.ReadInt64().ToString();
        }

        public string readscore()
        {
            return ReadInt64();
        }

        ///
        public Int16 ReadInt16()
        {
            setCurReadLength(getCurReadLength() + sizeof(Int16));
            return (Int16)reader.ReadInt16();
        }

        /// <readint>
        public Int32 ReadInt32()
        {
            setCurReadLength(getCurReadLength() + sizeof(Int32));
            return (Int32)reader.ReadInt32();
        }

        public Int32 readint()
        {
            return ReadInt32();
        }
        //

        public Single ReadSingle()
        {
            setCurReadLength(getCurReadLength() + sizeof(Single));
            return (Single)reader.ReadSingle();
        }

        public int ReadInt()
        {
            setCurReadLength(getCurReadLength() + sizeof(int));
            return (int)reader.ReadInt32();
        }

        /// <readshort>
        public short ReadShort()
        {
            setCurReadLength(getCurReadLength() + sizeof(short));
            return reader.ReadInt16();
        }

        public short readshort()
        {
            return ReadShort();
        }

        ///
        public long ReadLong()
        {
            setCurReadLength(getCurReadLength() + sizeof(long));
            long l = (long)reader.ReadInt64();
            Debug.Log(" l is " + l);
            return l;
        }

        /// <readfloat>
        public float ReadFloat()
        {
            return ReadSingle();
        }

        public float readfloat()
        {
            return ReadFloat();
        }

        /// 
        /// <readdouble>
        public double ReadDouble()
        {
            setCurReadLength(getCurReadLength() + sizeof(double));
            return reader.ReadDouble();
        }

        public double readdouble()
        {
            return ReadDouble();
        }

        /// 
        /// <readstring>
        public string ReadString(int length)
        {
            setCurReadLength(getCurReadLength() + length);
            byte[] buffer = new byte[length];
            buffer = reader.ReadBytes(length);
            return NetUtils.UTF16ByteArrayToString(buffer);
        }
        
        public string readstring(int length)
        {
            return ReadString(length);
        }

        public string ReadString()
        {
            int len = ReadShort();
            setCurReadLength(getCurReadLength() + len);
            byte[] buffer = new byte[len];
            buffer = reader.ReadBytes(len);
            return Encoding.UTF8.GetString(buffer);
        }

        public string readstring()
        {
            return ReadString();
        }

        ///
        public byte[] ReadBytes()
        {
            int len = ReadInt();
            setCurReadLength(getCurReadLength() + len);
            return reader.ReadBytes(len);
        }

        public byte[] ReadBytes(int length)
        {
            setCurReadLength(getCurReadLength() + length);
            return reader.ReadBytes(length);
        }

        /// <summary>
        /// 读取对象
        /// </summary>
        /// <returns></returns>
        public T ReadObject<T>()
        {
            int len = Marshal.SizeOf(typeof(T));
            setCurReadLength(getCurReadLength() + len);
            byte[] byteArray = new byte[len];
            byteArray = reader.ReadBytes(len);
            return NetUtils.bytesToStruct<T>(byteArray);
        }



        // public LuaByteBuffer ReadBuffer()
        // {
        //     byte[] bytes = ReadBytes();
        //     return new LuaByteBuffer(bytes);
        // }

        public byte[] ToBytes()
        {
            writer.Flush();
            return stream.ToArray();
        }

        public void Flush()
        {
            writer.Flush();
        }
    }
}